//****************************************************
// Porman Project 2
// Filename: CDeviceCreator.h
// Date: 2007/11/04
// Author: KengYu Lin
// Modify:
//****************************************************
#ifndef _CDEVICECREATOR_H
#define _CDEVICECREATOR_H

#include "CGLDef.h"
#include <vector>

namespace Porman
{

namespace GL
{

class CDeviceCreator;
class CRenderDevice;

class CDeviceDesc
{
    friend class CDeviceCreator;
public:
    PGL_API CDeviceDesc( void );
    PGL_API CDeviceDesc( const CDeviceDesc& l );
    PGL_API virtual ~CDeviceDesc( void );
    PGL_API CDeviceDesc& operator=( const CDeviceDesc& l );

    PGL_API void setColorFormat( int uiRedBits, int uiGreenBits, int uiBlueBits, int uiAlphaBits );
    PGL_API void setDepthFormat( int uiBits );
    PGL_API void setStencilFormat( int uiBits );
    PGL_API void setDoubleBuffer( bool bEnable );
    PGL_API void setSwapMethod( EDrawSurfaceSwapMethod enumSwapMethod );
    PGL_API void setAcceleration( EDrawSurfaceAcceleration enumAcceleration );

    PGL_API void setFormat( int iOption, int iValue );
    PGL_API void setFormat( float fOption, float fValue ); 

protected:
    int*   _outputAttributesInt( void ) const;
    float* _outputAttributesFloat( void ) const;

    struct SOptionInt
    {
        union
        {
            struct
            {
                int m_iOption;
                int m_iValue;
            };

            int m_iV[2];
        };
    };

    struct SOptionFloat
    {
        union
        {
            struct
            {
                float m_fOption;
                float m_fValue;
            };

            float m_fV[2];
        };
    };

protected:
    mutable std::vector<SOptionInt>   m_vectOptionInt;
    mutable std::vector<SOptionFloat> m_vectOptionFloat;

    mutable int*   m_pAttributesInt;
    mutable float* m_pAttributesFloat;
};

class CRenderCanvas
{
    friend class CDeviceCreator;
    friend class CRenderDevice;
public:
    HWND  m_hWnd;
    HDC   m_hDC;
    int   m_iPixelFormat;

protected:
    CRenderCanvas( void ) : m_hWnd(NULL), m_hDC(NULL), m_iPixelFormat(0) {}
    virtual ~CRenderCanvas( void ) { m_hWnd = NULL; m_hDC = NULL; m_iPixelFormat = 0; }

    CRenderCanvas( const CRenderCanvas& l );
    CRenderCanvas& operator= ( const CRenderCanvas& rc );
};

class CDeviceCreator
{
public:
    PGL_API static ERESULT createCanvas( const HWND hWnd, const CDeviceDesc* pSurfaceDec, CRenderCanvas** ppCanvas );
    PGL_API static void destroyCanvas( CRenderCanvas** ppCanvas );

    PGL_API static ERESULT createDevice( const CRenderCanvas* pSurface, CRenderDevice** ppRenderDevice );
    PGL_API static void destroyDevice( CRenderDevice** ppRenderDevice );

protected:
    CDeviceCreator( void );
    virtual ~CDeviceCreator( void ) {}

    static ERESULT _choosePixelFormat( const HWND hWnd, const CDeviceDesc* pSurfaceDec, int* pOutPixelFormat );
};

}//End namespace GL

}//End namespace Porman

#endif